package com.techsoul.module.system.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.techsoul.common.core.exception.ParamException;
import com.techsoul.common.core.pojo.TreeSelect;
import com.techsoul.common.core.pojo.vo.UserVo;
import com.techsoul.common.core.util.ServletUtils;
import com.techsoul.common.core.util.bean.BeanUtils;
import com.techsoul.common.core.util.collection.ListUtils;
import com.techsoul.common.core.util.lang.StringUtils;
import com.techsoul.common.security.service.TokenService;
import com.techsoul.module.system.mapper.RegionMapper;
import com.techsoul.module.system.pojo.entity.Region;
import com.techsoul.module.system.pojo.param.RegionSaveParam;
import com.techsoul.module.system.pojo.param.RegionSearchParam;
import com.techsoul.common.core.pojo.vo.RegionVo;
import com.techsoul.module.system.service.IRegionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 行政区域 Service实现
 * 
 * @author liuen
 * @date 2020-12-28
 */
@Service
@Transactional(readOnly = true)
public class RegionServiceImpl implements IRegionService {

    @Autowired
    private RegionMapper mapper;

    @Autowired
    private TokenService tokenService;

    /**
     * 新增
     * @param params
     * @return
     */
    @Transactional(readOnly = false)
    @Override
    public String insert(RegionSaveParam params) {
        UserVo user = tokenService.getLoginUser(ServletUtils.getRequest()).getUser();
        Region entity = new Region();
        BeanUtils.copyProperties(params, entity);
        entity.preInsert(user.getId());
        // 完善全节点信息
        if (StringUtils.isNotBlank(params.getPid()) && !StringUtils.equals("0",  params.getPid())) {
            Region parent = this.mapper.selectById(params.getPid());
            entity.setTreeLevel(parent.getTreeLevel() + 1);
            String ancestorNames = parent.getRegionName();
            if (StringUtils.isNotBlank(parent.getAncestorNames())) {
                ancestorNames = parent.getAncestorNames() + "/" + parent.getRegionName();
            }
            String ancestorIds = parent.getId();
            if (StringUtils.isNotBlank(parent.getAncestorIds())) {
                ancestorIds = parent.getAncestorIds() + "," + parent.getId();
            }
            entity.setAncestor(ancestorIds, ancestorNames);
            entity.setRegionFullName(entity.getAncestorNames() + "/" + entity.getRegionName());
        } else {
            entity.setAncestor("", "");
            entity.setRegionFullName(entity.getRegionName());
        }
        this.mapper.insert(entity);
        return entity.getId();
    }

    /**
     * 删除
     * @param id
     * @return
     */
    @Transactional(readOnly = false)
    @Override
    public Integer delete(String id) {
        return this.mapper.deleteById(id);
    }

    /**
     * 批量删除
     * @param idList
     */
    @Transactional(readOnly = false)
    @Override
    public Integer batchDelete(List<String> idList) {
        if (ListUtils.isNotEmpty(idList)) {
            return this.mapper.deleteBatchIds(idList);
        } else {
            return 0;
        }
    }

    /**
     * 修改
     * @param params
     * @return
     */
    @Transactional(readOnly = false)
    @Override
    public Integer update(RegionSaveParam params) {
        Region entityFromDb = this.mapper.selectById(params.getId());
        if (entityFromDb == null) {
            throw new ParamException("id=" + params.getId());
        }
        UserVo user = tokenService.getLoginUser(ServletUtils.getRequest()).getUser();
        BeanUtils.copyProperties(params, entityFromDb);
        entityFromDb.preUpdate(user.getId());
        // 完善全节点信息
        if (StringUtils.isNotBlank(params.getPid()) && !StringUtils.equals("0",  params.getPid())) {
            Region parent = this.mapper.selectById(params.getPid());
            entityFromDb.setTreeLevel(parent.getTreeLevel() + 1);
            String ancestorNames = parent.getRegionName();
            if (StringUtils.isNotBlank(parent.getAncestorNames())) {
                ancestorNames = parent.getAncestorNames() + "/" + parent.getRegionName();
            }
            String ancestorIds = parent.getId();
            if (StringUtils.isNotBlank(parent.getAncestorIds())) {
                ancestorIds = parent.getAncestorIds() + "," + parent.getId();
            }
            entityFromDb.setAncestor(ancestorIds, ancestorNames);
            entityFromDb.setRegionFullName(entityFromDb.getAncestorNames() + "/" + entityFromDb.getRegionName());
        } else {
            entityFromDb.setAncestor("", "");
            entityFromDb.setRegionFullName(entityFromDb.getRegionName());
        }
        entityFromDb.setRegionFullName(entityFromDb.getAncestorNames() + "/" + entityFromDb.getRegionName());
        return this.mapper.updateById(entityFromDb);
    }

    /**
     * 更新树形表信息
     */
    @Transactional(readOnly = false)
    @Override
    public void updateAll() {
        List<RegionVo> list = this.findAll(new RegionSearchParam());
        if (ListUtils.isNotEmpty(list)) {
            list.forEach(obj -> {
                RegionSaveParam saveParam = new RegionSaveParam();
                BeanUtils.copyBeanProp(saveParam, obj);
                this.update(saveParam);
            });
        }
    }

    /**
     * 详情
     * @param id
     * @return
     */
    @Override
    public RegionVo findById(String id) {
        return this.mapper.findById(id);
    }

    /**
     * 列表
     * @param params
     * @return
     */
    @Override
    public List<RegionVo> findAll(RegionSearchParam params) {
        return this.mapper.findAll(params);
    }

    /**
     * 层级列表
     * @param treeLevel
     * @return
     */
    @Override
    public List<RegionVo> findLevelList(Integer treeLevel) {
        return this.mapper.findLevelList(treeLevel);
    }

    /**
     * 列表-分页
     * @param params
     * @param current
     * @param pageSize
     * @return
     */
    @Override
    public IPage<RegionVo> findAll(RegionSearchParam params, Integer current, Integer pageSize) {
        return this.mapper.findAll(new Page<>(current, pageSize), params);
    }

    /**
     * 树形结构数据
     * @param params
     * @return
     */
    @Override
    public List<RegionVo> findTree(RegionSearchParam params) {
        List<RegionVo> list = this.mapper.findAll(params);
        return this.buildTree(list);
    }

    /**
     * 树形结构选择器数据
     * @param params
     * @return
     */
    @Override
    public List<TreeSelect> findTreeSelect(RegionSearchParam params) {
        List<RegionVo> list = this.mapper.findAll(params);
        return this.buildTreeSelect(list);
    }


    /**
     * 构建树形结构数据
     *
     * @param list
     * @return
     */
    @Override
    public List<RegionVo> buildTree(List<RegionVo> list) {
        List<RegionVo> returnList = new ArrayList<>();
        List<String> tempList = new ArrayList<>();
        // 获取所有的节点ID
        for (RegionVo node : list) {
            tempList.add(node.getId());
        }
        for (Iterator<RegionVo> iterator = list.iterator(); iterator.hasNext();) {
            RegionVo node = iterator.next();
            // 如果是顶级节点（父节点不在tempList里，则默认为顶级节点）, 遍历该父节点的所有子节点
            if (!tempList.contains(node.getPid())) {
                recursionGenChildren(list, node);
                returnList.add(node);
            }
        }
        if (returnList.isEmpty()) {
            returnList = list;
        }
        return returnList;
    }

    /**
     * 构建树形结构选择器数据
     *
     * @param list
     * @return
     */
    @Override
    public List<TreeSelect> buildTreeSelect(List<RegionVo> list) {
        List<RegionVo> tree = buildTree(list);
        return tree.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChildren(List<RegionVo> list, RegionVo parent) {
        return getChildrens(list, parent).size() > 0 ? true : false;
    }

    /**
     * 获取子节点列表
     * @param list
     * @param parent
     * @return
     */
    private List<RegionVo> getChildrens(List<RegionVo> list, RegionVo parent) {
        List<RegionVo> childrens = new ArrayList<>();
        Iterator<RegionVo> iterator = list.iterator();
        while (iterator.hasNext()) {
            RegionVo children = iterator.next();
            if (StringUtils.isNotBlank(children.getPid()) && parent.getId().equals(children.getPid())) {
                childrens.add(children);
            }
        }
        return childrens;
    }

    /**
     * 递归生成父节点下所有节点的children
     * @param list
     * @param parent
     */
    private void recursionGenChildren(List<RegionVo> list, RegionVo parent) {
        List<RegionVo> childList = getChildrens(list, parent);
        parent.setChildren(childList);
        for (RegionVo tChild : childList) {
            if (hasChildren(list, tChild)) {
                recursionGenChildren(list, tChild);
            }
        }
    }

}
